Виджеты. Checkbox FAB AlertDialog Switch
➡️Ссылка на репозиторий с кодом этого урока
Виджет Switch
Виджет Switch - это переключатель между двумя значениями (вкл/выкл). Он часто используется для настроек.
Switch(
value: widget.isDarkMode,
onChanged: widget.onThemeToggle,
),
Основные свойства Switch:
value:bool- текущее состояние переключателя (true- включен,false- выключен).onChanged: - колбэк-функция, вызываемая при изменении состояния переключателя пользователем. Эта функция принимает новое состояние (trueилиfalse). Как и дляCheckbox, внутриonChangedмы обычно вызываемsetState()для обновления UI.
Для смены темы нам нужно управлять свойством themeMode виджета MaterialApp. Поскольку MaterialApp находится выше в дереве виджетов, чем наш TaskListScreen, нам потребуется поднять состояние темы выше или использовать простой механизм передачи данных вниз и колбэков вверх. Для этого примера мы сделаем MyApp StatefulWidget и будем передавать текущую тему и функцию переключения в TaskListScreen.
Смена цветовой темы приложения через Switch
Изменим MyApp, чтобы он стал StatefulWidget и управлял темой, а затем передадим эту логику в TaskListScreen через конструктор.

Файл main.dart
void main() {
runApp(const ToDoApp());
}
class ToDoApp extends StatefulWidget {
const ToDoApp({super.key});
@override
State<ToDoApp> createState() => _ToDoAppState();
}
class _ToDoAppState extends State<ToDoApp> {
// Состояние темы: true - тёмная, false - светлая
bool _isDarkMode = false;
// Метод для переключения темы
void _toggleTheme(bool newValue) {
setState(() {
_isDarkMode = newValue;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Список Дел",
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue), // Цвета
),
darkTheme: ThemeData.dark(),
themeMode: _isDarkMode ? ThemeMode.dark : ThemeMode.light, // Текущая тема
debugShowCheckedModeBanner: false,
// Передаем состояние темы и функцию переключения в TaskListScreen
home: ToDoScreen(
isDarkMode: _isDarkMode,
onThemeToggle: _toggleTheme,
),
);
}
}
Добавим виджет Switch в AppBar Scaffold → AppBar → actions
Файл todo_screen.dart
import 'package:flutter/material.dart';
import '../models/task.dart';
class ToDoScreen extends StatefulWidget {
final bool isDarkMode;
final ValueChanged<bool> onThemeToggle; // Функция для переключения темы
const ToDoScreen({
super.key,
required this.isDarkMode,
required this.onThemeToggle,
});
@override
State<ToDoScreen> createState() => _ToDoScreenState();
}
class _ToDoScreenState extends State<ToDoScreen> {
// Контроллер для ввода текста
TextEditingController textEditingController = TextEditingController();
// Список задач
final List<Task> _tasks = [
Task(text: 'Купить молоко'),
Task(text: 'Изучить нейронки'),
Task(text: 'Купить RTX 5090', isDone: true), // Пример выполненной задачи
];
// Метод для показа диалога добавления задачи
void showAddTaskDialog() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Добавить новую задачу'),
content: TextField(
controller: textEditingController,
decoration: const InputDecoration(hintText: "Введите текст задачи"),
),
actions: <Widget>[
// Кнопка отмены
TextButton(
child: const Text('Отмена'),
onPressed: () {
Navigator.of(context).pop(); // Закрыть диалог
},
),
// Кнопка добавления
TextButton(
child: const Text('Добавить'),
onPressed: () {
setState(() {
// Добавляем задачу в список
_tasks.add(Task(text: textEditingController.text));
// Очищаем контроллер
textEditingController.clear();
});
Navigator.of(context).pop(); // Закрыть диалог
},
),
],
);
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Список Задач'),
actions: [
Center(
child: Text(widget.isDarkMode ? 'Темная тема' : 'Светлая тема'),
),
Switch(
// Значение Switch зависит от переданного состояния
value: widget.isDarkMode,
// При изменении вызываем переданную функцию
onChanged: widget.onThemeToggle,
),
const SizedBox(width: 8), // Небольшой отступ справа
],
),
// Добавляем FAB
body: ListView.builder(
itemCount: _tasks.length, // Количество задач
itemBuilder: (context, index) {
final task = _tasks[index]; // Текущая задача
return ListTile(
// Чекбокс слева
leading: Checkbox(
value: task.isDone, // значение выполненности из объекта task
onChanged: (bool? newValue) {
// При изменении чекбокса, переключаем статус задачи
setState(() {
task.isDone = newValue ?? false; // Меняем статус на новый
});
},
),
// Текст задачи с зачеркиванием
title: Text(
task.text,
style: TextStyle(
decoration:
task.isDone
? TextDecoration.lineThrough // Зачеркнутый, если выполнена
: TextDecoration.none, // Обычный, если не выполнена
),
),
);
},
),
floatingActionButton: FloatingActionButton.extended(
onPressed: showAddTaskDialog, // Вызываем метод показа диалога
label: const Text('Добавить'), // Текст на кнопке
icon: const Icon(Icons.add), // Иконка на кнопке
tooltip: 'Добавить новую задачу',
),
);
}
}


